﻿<script setup lang="ts" name="CardList">
import { storeToRefs } from 'pinia'
import { useSystemConfigStore } from '@/store/storage/systemConfigStore'
import slot_16x9 from '@/assets/slot_16x9.png'
import { getWebsiteList, getWebsitePageList, getPageList, getModuleList } from '@/api/website'
import WebsiteAddEdit from '../WebsiteAddEdit/index.vue'
import FullScreenWrap from '../FullScreenWrap/index.vue'
import PageDesigner from '../PageDesigner/index.vue'
import ModuleAddEdit from '../ModuleAddEdit/index.vue'
import PageAddEdit from '../PageAddEdit/index.vue'
import { templateRef, useResizeObserver, useDebounceFn } from '@vueuse/core'
import XEUtils from 'xe-utils'
import { cloneDeep } from 'lodash-es'
import useDictionaryEntry from '@/hooks/useDictionaryEntry'
const { getDictionaryEntryData } = useDictionaryEntry()
const systemConfigStore = useSystemConfigStore()
const { systemConfig } = storeToRefs(systemConfigStore)
const props = defineProps({
  cardType: { type: String }
})
const pageData: any = ref({
  listData: {
    imagePreviewList: [],
    total: 0,
    data: [],
    waterfallData: []
  },
  currentWebsite: null,
  searchData: {
    industry: '',
    device: [],
    title: '',
    status: 1,
    pageType: '',
    moduleType: []
  }
})
const pageIndex = ref(1)
const pageSize = ref(20)

const statusList = ref([])
const getStatusList = async () => {
  console.log('获取状态数据')
  statusList.value = await getDictionaryEntryData({
    label: '',
    status: 2,
    type: 'enable_number'
  })
}
getStatusList()
const industryList = ref([])
const getIndustryList = async () => {
  console.log('获取状态数据')
  industryList.value = await getDictionaryEntryData({
    label: '',
    status: 2,
    type: 'industry'
  })
}
getIndustryList()
const pageTypeList = ref([])
const getPageTypeList = async () => {
  console.log('获取状态数据')
  pageTypeList.value = await getDictionaryEntryData({
    label: '',
    status: 2,
    type: 'pageType'
  })
}
getPageTypeList()
const moduleTypeList = ref([])
const getModuleTypeList = async () => {
  console.log('获取状态数据')
  moduleTypeList.value = await getDictionaryEntryData({
    label: '',
    status: 2,
    type: 'moduleType'
  })
}
getModuleTypeList()
const deviceList = ref([])
const getDeviceList = async () => {
  console.log('获取状态数据')
  deviceList.value = await getDictionaryEntryData({
    label: '',
    status: 2,
    type: 'device'
  })
}
getDeviceList()

// 页面数据条数改变重新获取数据
const handleSizeChange = (val: number) => {
  pageSize.value = val
  pageIndex.value = 1
  getInitData()
}
// 当前页改变重新获取数据
const handleCurrentChange = (val: number) => {
  pageIndex.value = val
  getInitData()
}
// 重置页面数据
const resetPageData = () => {
  pageData.value.listData.data = []
  pageData.value.listData.waterfallData = []
  currentRenderIndex.value = 0
  pageData.value.listData.total = 0
  pageData.value.listData.imagePreviewList = []
  lastRender.value = false
}

const getDeviceData = (data) => {
  let result = ''
  deviceList.value.forEach((item) => {
    if (item.label === data) {
      result = item.value
    }
  })
  return result
}
const getIndustryValue = (data) => {
  let result = []
  industryList.value.forEach((item) => {
    if (item.label === data) {
      result = [item.value]
    }
  })
  return result
}
// 获取当前查询条件下的数据
const getInitData = () => {
  resetPageData()
  const result: any = {}
  result.pageIndex = pageIndex.value
  result.pageSize = pageSize.value
  result.title = pageData.value.searchData.title
  if (props.cardType === 'page') {
    result.pageType = pageData.value.searchData.pageType
    result.industry = pageData.value.searchData.industry
    result.device = pageData.value.searchData.device
    getPageList(result, { config: { showLoading: false, mockEnable: true } }).then((res: any) => {
      console.log(res)
      if (res.data && res.data.length > 0) {
        setTimeout(() => {
          res.data.forEach(function (item) {
            item.imageLoaded = 'loading'
            pageData.value.listData.data.push(item)
            pageData.value.listData.imagePreviewList.push(item.src)
          })
          pageData.value.listData.total = res.total
          renderList(true)
        }, 1000)
      }
    })
  } else if (props.cardType === 'module') {
    result.moduleType = pageData.value.searchData.moduleType
    result.industry = pageData.value.searchData.industry
    getModuleList(result, { config: { showLoading: false, mockEnable: true } }).then((res: any) => {
      console.log(res)
      if (res.data && res.data.length > 0) {
        setTimeout(() => {
          res.data.forEach(function (item) {
            item.imageLoaded = 'loading'
            pageData.value.listData.data.push(item)
            pageData.value.listData.imagePreviewList.push(item.src)
          })
          pageData.value.listData.total = res.total
          renderList(true)
        }, 1000)
      }
    })
  } else if (props.cardType === 'websitePage') {
    result.pageType = pageData.value.searchData.pageType
    result.status = pageData.value.searchData.status
    result.industry = getIndustryValue(pageData.value.currentWebsite.industry)
    result.device = getDeviceData(pageData.value.currentWebsite.device)
    console.log(result)
    getWebsitePageList(result, { config: { showLoading: false, mockEnable: true } }).then((res: any) => {
      console.log(res)
      if (res.data && res.data.length > 0) {
        setTimeout(() => {
          res.data.forEach(function (item) {
            item.imageLoaded = 'loading'
            pageData.value.listData.data.push(item)
            pageData.value.listData.imagePreviewList.push(item.src)
          })
          pageData.value.listData.total = res.total
          renderList(true)
        }, 1000)
      }
    })
  } else if (props.cardType === 'website') {
    result.industry = pageData.value.searchData.industry
    result.device = pageData.value.searchData.device
    getWebsiteList(result, { config: { showLoading: false, mockEnable: true } }).then((res: any) => {
      console.log(res)
      if (res.data && res.data.length > 0) {
        setTimeout(() => {
          res.data.forEach(function (item) {
            item.imageLoaded = 'loading'
            pageData.value.listData.data.push(item)
            pageData.value.listData.imagePreviewList.push(item.src)
          })
          pageData.value.listData.total = res.total
          renderList(true)
        }, 1000)
      }
    })
  }
}
// 暴露获取数据方法给父组件
defineExpose({ getInitData })
// 删除模板点击事件
const remove = (item) => {
  const msg = '是否确认删除该' + cardTypeCn.value + '模板？'
  ElMessageBox.alert(msg, '警告', {
    showCancelButton: true,
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    callback: (action) => {
      if (action === 'confirm') {
        ElMessage({
          type: 'info',
          message: `操作: 点击了确认`
        })
      } else {
        ElMessage({
          type: 'info',
          message: `操作: 点击了取消`
        })
      }
    }
  })
}

const addEditType = ref('')
const cardTypeCn = ref('')
// 监听当前列表类型
watch(
  () => props.cardType,
  (v) => {
    getCardType(v)
  }
)
// 获取当前列表类型
const getCardType = (v) => {
  switch (v) {
    case 'website':
      cardTypeCn.value = '站点'
      break
    case 'module':
      cardTypeCn.value = '模块'
      break
    default:
      cardTypeCn.value = '页面'
      break
  }
}
const drawerConfig: any = ref({})
const websiteAddEditRef = ref(null)
const moduleAddEditRef = ref(null)
const pageAddEditRef = ref(null)
// 新增事件
const add = () => {
  drawerConfig.value.type = 'add'
  addEditType.value = '新建'
  drawerConfig.value.options = null
  if (props.cardType === 'websitePage') {
    drawerConfig.value.options = {}
    drawerConfig.value.options.industry = pageData.value.currentWebsite.industry
    drawerConfig.value.options.device = pageData.value.currentWebsite.device
  }
  getCardType(props.cardType)
  addEdit()
}
// 编辑事件
const edit = (item = undefined) => {
  drawerConfig.value.type = 'edit'
  addEditType.value = '编辑'
  drawerConfig.value.options = item
  getCardType(props.cardType)
  addEdit()
}
// 新增/编辑点击事件
const addEdit = () => {
  drawerConfig.value.title = addEditType.value + cardTypeCn.value
  switch (props.cardType) {
    case 'website':
      drawerConfig.value.category = 'website'
      websiteAddEditRef.value.showDrawerWrap(drawerConfig.value)
      break
    case 'module':
      drawerConfig.value.category = 'module'
      moduleAddEditRef.value.showDrawerWrap(drawerConfig.value)
      break
    case 'websitePage':
      drawerConfig.value.category = 'websitePage'
      pageAddEditRef.value.showDrawerWrap(drawerConfig.value)
      break
    default:
      drawerConfig.value.category = 'page'
      pageAddEditRef.value.showDrawerWrap(drawerConfig.value)
      break
  }
}

const pageDesignerRef = ref(null)
// 页面装修点击事件
const pageDesigner = (item) => {
  console.log(item, '当前装修页面信息')
  console.log(pageData.value.currentWebsite, '当前装修公司信息')
  const result: any = {}
  result.device = item.device
  result.industry = item.industry
  result.pageName = item.title
  result.pageType = item.pageType
  if (props.cardType === 'websitePage') {
    result.width = pageData.value.currentWebsite.width
    result.primaryColor = pageData.value.currentWebsite.color
    result.websiteName = pageData.value.currentWebsite.title
    result.title = result.websiteName + '公司 - ' + result.industry + '行业 - ' + result.device + ' - ' + result.pageType + ' - ' + result.pageName + '页面装修'
  } else {
    result.width = 1500
    result.primaryColor = '#1890ff'
    result.websiteName = ''
    result.title = result.industry + '行业 - ' + result.device + ' - ' + result.pageType + ' - ' + result.pageName + '页面装修'
  }
  console.log(result, '页面布局装修组装数据')
  pageDesignerRef.value.showPageDesigner(result)
}

const previewRef = ref(null)
// 预览点击事件
const preview = (item) => {
  const title = cardTypeCn.value + '预览'
  previewRef.value.showDialog({ title: title })
}
// 站点列表切换到站点页面列表
const emit = defineEmits(['update:cardType'])
// 站点页面管理
const pageManagement = (item) => {
  console.log(item, '页面管理')
  pageData.value.currentWebsite = item
  emit('update:cardType', 'websitePage')
  nextTick(() => {
    pageData.value.listData.waterfallData = []
    currentRenderIndex.value = 0
    lastRender.value = false
    getInitData()
  })
}
// 返回站点列表
const backWebsite = () => {
  emit('update:cardType', 'website')
  pageData.value.currentWebsite = null
  pageData.value.searchData.device = []
  pageData.value.searchData.industry = ''
  pageData.value.searchData.width = ''
  pageData.value.searchData.pageType = ''
  pageData.value.searchData.title = ''
  pageData.value.searchData.status = 1
  nextTick(() => {
    pageData.value.listData.waterfallData = []
    currentRenderIndex.value = 0
    lastRender.value = false
    getInitData()
  })
}
// 复制网站/页面模板
const copy = (item) => {
  const msg = '是否确认复制一份当前' + cardTypeCn.value + '模板？'
  ElMessageBox.alert(msg, '警告', {
    showCancelButton: true,
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    callback: (action) => {
      if (action === 'confirm') {
        ElMessage({
          type: 'info',
          message: `操作: 点击了确认`
        })
      } else {
        ElMessage({
          type: 'info',
          message: `操作: 点击了取消`
        })
      }
    }
  })
}
// 复制并释放网站页面模板
const copyFreed = (item) => {
  const msg = '该操作会将当前页面模板复制并释放到页面模板池内，可被其它站点选择，是否确认复制并释放？'
  ElMessageBox.alert(msg, '警告', {
    showCancelButton: true,
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    callback: (action) => {
      if (action === 'confirm') {
        ElMessage({
          type: 'info',
          message: `操作: 点击了确认`
        })
      } else {
        ElMessage({
          type: 'info',
          message: `操作: 点击了取消`
        })
      }
    }
  })
}
// 下载模板
const download = (item) => {
  console.log(item)
  ElMessage({
    type: 'success',
    message: '下载完成！'
  })
}
// 查询条件重置
const resetSearch = () => {
  pageData.value.searchData.industry = ''
  pageData.value.searchData.device = []
  pageData.value.searchData.title = ''
  pageData.value.searchData.status = 1
  pageData.value.searchData.pageType = ''
  pageData.value.searchData.moduleType = []
  getInitData()
}
onMounted(() => {
  getCardType(props.cardType)
})
const imageBox = templateRef<HTMLElement | null>('imageBox', null)
const waterFull = templateRef<HTMLElement | null>('waterFull', null)
const currentRenderIndex = ref(0)
const imageLoadSuccess = (e, v) => {
  pageData.value.listData.waterfallData.forEach((item, index) => {
    if (item.id === v.id) {
      item.imageLoaded = 'success'
      nextTick(() => {
        setTimeout(() => {
          if (index + 1 < pageData.value.listData.data.length) {
            updateRenderIndex(index + 1)
          } else {
            lastRenderHandler()
          }
        }, 10)
      })
    }
  })
}
const imageLoadError = (e, v) => {
  pageData.value.listData.waterfallData.forEach((item, index) => {
    if (item.id === v.id) {
      item.imageLoaded = 'error'
      nextTick(() => {
        setTimeout(() => {
          if (index + 1 < pageData.value.listData.data.length) {
            updateRenderIndex(index + 1)
          } else {
            lastRenderHandler()
          }
        }, 10)
      })
    }
  })
}

const columnCount = ref(4)
const columnStyleHeight = ref([])
const maxHeight = ref(0)
const lastRender = ref(false)
const updateRenderIndex = (index) => {
  console.log('更新渲染的当前索引', index)
  console.log('更新渲染的上一个索引', currentRenderIndex.value)
  if (index > currentRenderIndex.value) {
    currentRenderIndex.value = index
    const minColIndex = getMinHeightIndex(columnStyleHeight.value)
    columnStyleHeight.value[minColIndex] += imageBox.value[currentRenderIndex.value - 1].offsetHeight
    maxHeight.value = XEUtils.max(columnStyleHeight.value, item => item) + 10
    renderList(true)
  } else {
    renderList(false)
  }
}
const lastRenderHandler = () => {
  if (!lastRender.value) {
    lastRender.value = true
    const minColIndex = getMinHeightIndex(columnStyleHeight.value)
    columnStyleHeight.value[minColIndex] += imageBox.value[currentRenderIndex.value].offsetHeight
    maxHeight.value = XEUtils.max(columnStyleHeight.value, item => item) + 10
  }
}
const renderList = (isAdd) => {
  const newItem = cloneDeep(pageData.value.listData.data[currentRenderIndex.value])
  if (pageData.value.listData.waterfallData.length === 0) {
    columnStyleHeight.value = []
    for (let i = 0; i < columnCount.value; i++) {
      columnStyleHeight.value.push(systemConfig.value.space / 2)
    }
    newItem.styleObj = {
      width: (100 / columnCount.value) + '%',
      left: '0%',
      top: systemConfig.value.space / 2 + 'px'
    }
  } else {
    const minColIndex = getMinHeightIndex(columnStyleHeight.value)
    newItem.styleObj = {
      width: (100 / columnCount.value) + '%',
      left: minColIndex * (100 / columnCount.value) + '%',
      top: columnStyleHeight.value[minColIndex] + 'px'
    }
  }
  if (isAdd) {
    pageData.value.listData.waterfallData.push(newItem)
  } else {
    pageData.value.listData.waterfallData[currentRenderIndex.value].styleObj = newItem.styleObj
  }
}
// 监听元素尺寸变化
useResizeObserver(
  document.body,
  useDebounceFn(() => {
    waterFullResize()
  }, 200)
)
const waterFullResize = () => {
  const rect = document.body.getBoundingClientRect()
  console.log(rect)
  if (rect.width > 1720) {
    columnCount.value = 4
  } else if (rect.width > 1200 && rect.width <= 1720) {
    columnCount.value = 3
  } else if (rect.width > 768 && rect.width <= 1200) {
    columnCount.value = 2
  } else {
    columnCount.value = 1
  }
  console.log('走监听了')
  if (pageData.value.listData.data.length > 0) {
    pageData.value.listData.waterfallData = []
    currentRenderIndex.value = 0
    lastRender.value = false
    renderList(true)
  }
}

// 获取图片高度最小的索引值
const getMinHeightIndex = (arr) => {
  return arr.indexOf(Math.min(...arr))
}

const moduleTypeChangeHandler = (value) => {
  console.log(value)
}
</script>

<template>
  <div class="card-list-page">
    <el-page-header icon="ArrowLeft" v-if="cardType === 'websitePage'" @back="backWebsite">
      <template #content>
        <span>
          <span v-if="pageData.currentWebsite">{{ pageData.currentWebsite.industry }} -{{ pageData.currentWebsite.title }} - {{ pageData.currentWebsite.device }} -</span>
          页面管理
        </span>
      </template>
    </el-page-header>
    <el-form :inline="true">
      <el-form-item label="类型" v-if="cardType === 'page' || cardType === 'websitePage'">
        <el-select v-model="pageData.searchData.pageType" placeholder="选择页面类型">
          <el-option v-for="item in pageTypeList" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item label="分类" v-if="cardType === 'module'">
        <el-cascader v-model="pageData.searchData.moduleType" :props="{ checkStrictly: true }" clearable :options="moduleTypeList" placeholder="选择模块分类" @change="moduleTypeChangeHandler" />
      </el-form-item>
      <el-form-item label="行业" v-if="cardType !== 'websitePage'">
        <el-select v-model="pageData.searchData.industry" placeholder="选择行业">
          <el-option v-for="item in industryList" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item label="平台" v-if="cardType === 'website' || cardType === 'page'">
        <el-checkbox-group class="checkbox-button" v-model="pageData.searchData.device">
          <el-checkbox-button v-for="(item, index) in deviceList" :key="index" :label="item.value">
            {{ item.label
            }}
          </el-checkbox-button>
        </el-checkbox-group>
      </el-form-item>
      <el-form-item label="状态" v-if="cardType === 'websitePage'">
        <el-radio-group class="radio-button" v-model="pageData.searchData.status">
          <el-radio-button v-for="(item, index) in statusList" :key="index" :label="item.value">
            {{ item.label
            }}
          </el-radio-button>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="名称">
        <el-input v-model="pageData.searchData.title" placeholder="请输入名称" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="getInitData">查询</el-button>
        <el-button icon="Refresh" @click="resetSearch">重置</el-button>
        <el-button type="success" icon="Plus" @click="add()">{{ '新建' + cardTypeCn }}</el-button>
      </el-form-item>
    </el-form>
    <div class="water-full clearfix" ref="waterFull" :style="{ height: maxHeight + 'px' }" v-if="pageData.listData.waterfallData.length > 0">
      <template v-for="(item, index) in pageData.listData.waterfallData" :key="item.id">
        <div :class="['item-col', item.imageLoaded !== 'loading' ? 'is-show' : '']" :style="item.styleObj" ref="imageBox">
          <div class="item-card is-hover-shadow">
            <div :class="['image-wrap', 'image-load-' + item.imageLoaded]">
              <div class="image-mask"></div>
              <el-image :src="item.src" :preview-teleported="true" :preview-src-list="pageData.listData.imagePreviewList" :initial-index="index" lazy @load="(e) => { imageLoadSuccess(e, item) }" @error="(e) => { imageLoadError(e, item) }">
                <template #placeholder>
                  <div class="image-slot">
                    <img :src="slot_16x9" />
                    <div class="slot-content">
                      <svg-icon icon="ep:picture"></svg-icon>
                      <p>{{ $t('settings.settingLoadingText') }}</p>
                    </div>
                  </div>
                </template>
                <template #error>
                  <div class="image-slot">
                    <img :src="slot_16x9" />
                    <div class="slot-content">
                      <svg-icon icon="ii:icon-image-failed"></svg-icon>
                      <p>{{ $t('settings.settingLoadingFailed') }}</p>
                    </div>
                  </div>
                </template>
              </el-image>
            </div>
            <div class="item-title">
              {{ item.title }}
            </div>
            <div class="item-tag">
              <el-tag :color="item.color" v-if="cardType === 'website'"></el-tag>
              <el-tag v-if="cardType === 'page' || cardType === 'websitePage'">{{ item.pageType }}</el-tag>
              <el-tag :type="item.status ? 'success' : 'danger'" v-if="cardType === 'websitePage'">
                {{ item.status ? '已启用'
                  : '已禁用' }}
              </el-tag>
              <el-tag type="success" v-if="cardType === 'module'">{{ item.module }}</el-tag>
              <el-tag type="success" v-if="cardType === 'website' || cardType === 'page'">{{ item.device }}</el-tag>
              <el-tag type="danger" v-if="cardType === 'website' || cardType === 'page' || cardType === 'module'">
                {{
                  item.industry }}
              </el-tag>
              <el-tag type="warning" v-if="cardType === 'website' && item.device === '桌面端'">{{ item.width }}</el-tag>
            </div>
            <div class="item-description">{{ item.description }}</div>
            <div class="item-button">
              <svg-icon icon="ri:eye-line" title="预览" @click="preview(item)"></svg-icon>
              <svg-icon icon="ri:file-copy-line" title="复制" v-if="cardType === 'website' || cardType === 'websitePage' || cardType === 'page'" @click="copy(item)"></svg-icon>
              <svg-icon icon="ri:file-transfer-line" title="复制并释放" v-if="cardType === 'websitePage'" @click="copyFreed(item)"></svg-icon>
              <svg-icon icon="ri:file-settings-line" title="页面管理" v-if="cardType === 'website'" @click="pageManagement(item)"></svg-icon>
              <svg-icon icon="ri:file-edit-line" title="页面装修" v-if="cardType === 'websitePage' || cardType === 'page'" @click="pageDesigner(item)"></svg-icon>
              <svg-icon icon="ri:edit-box-line" title="编辑" @click="edit(item)"></svg-icon>
              <svg-icon icon="ri:delete-bin-5-line" title="删除" @click="remove(item)"></svg-icon>
              <svg-icon icon="ri:download-2-line" title="下载" v-if="cardType === 'website'" @click="download(item)"></svg-icon>
            </div>
          </div>
        </div>
      </template>
    </div>
    <el-pagination
      v-if="pageData.listData.total > 0"
      v-model:currentPage="pageIndex"
      v-model:page-size="pageSize"
      :page-sizes="[20, 40, 100, 200]"
      :background="true"
      layout="total, sizes, prev, pager, next, jumper"
      :total="pageData.listData.total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange" />
    <WebsiteAddEdit ref="websiteAddEditRef" :deviceList="deviceList" :industryList="industryList"></WebsiteAddEdit>
    <PageAddEdit ref="pageAddEditRef" :deviceList="deviceList" :industryList="industryList" :pageTypeList="pageTypeList"></PageAddEdit>
    <ModuleAddEdit ref="moduleAddEditRef" :industryList="industryList" :moduleTypeList="moduleTypeList"></ModuleAddEdit>
    <PageDesigner ref="pageDesignerRef"></PageDesigner>
    <FullScreenWrap ref="previewRef"></FullScreenWrap>
  </div>
</template>

<style scoped lang="scss">
.card-list-page {
  display: block;
  width: 100%;

  .el-page-header {
    margin-bottom: 14px;
  }

  :deep(.el-page-header__breadcrumb) {
    margin-bottom: 0
  }
}

.water-full {
  position: relative;
  margin-right: calc(0px - var(--el-space) / 2);
  margin-left: calc(0px - var(--el-space) / 2);
  padding-top: calc(var(--el-space) / 2);
  padding-bottom: calc(var(--el-space) / 2);

  .item-col {
    position: absolute;
    display: flex;
    float: left;
    padding: calc(var(--el-space) / 2);
    transform: scale(0.8);
    visibility: hidden;
    opacity: 0;
    transition: transform 0.3s, opacity 0.3s;

    &.is-show {
      transform: scale(1);
      visibility: inherit;
      opacity: 1
    }

    .item-card {
      flex: 1;
      overflow: hidden;
      color: var(--el-text-color-primary);
      background-color: var(--el-fill-color-blank);
      border: 1px solid var(--el-border-color-light);
      border-radius: calc(var(--el-border-radius-base) * 2);
      transition: var(--el-transition-duration);

      &.is-hover-shadow {
        &:hover {
          box-shadow: var(--el-box-shadow-light);
        }
      }

      .image-wrap {
        position: relative;
        margin: 20px;
        overflow: hidden;

        &.image-load-error,
        &.image-load-loading {
          :deep(.el-image__wrapper) {
            position: relative;
          }
        }

        &.image-load-loading {
          :deep(.el-image) {
            .is-loading {
              display: none;
            }
          }
        }

        .image-mask {
          overflow: hidden;
        }

        :deep(.el-image) {
          display: block;

          .el-image__inner {
            height: auto !important;
          }
        }
      }

      .item-tag {
        display: flex;
        align-items: flex-start;
        justify-content: flex-start;
        margin: 5px 17px 10px;

        .el-tag {
          margin: 3px;
        }
      }

      .item-title {
        height: 24px;
        margin: 15px 20px 10px;
        overflow: hidden;
        font-weight: 700;
        font-size: 16px;
        white-space: nowrap;
        text-overflow: ellipsis;
      }

      .item-description {
        margin: 0 20px 10px;
        opacity: 0.7;
      }

      .item-button {
        display: flex;
        border-top: 1px solid var(--el-border-color-light);

        .el-icon {
          flex: 1;
          height: 36px;
          cursor: pointer;

          &:hover {
            color: var(--el-color-primary);
          }

          &.enable {
            color: var(--el-color-success);
          }

          &.disabled {
            color: var(--el-color-danger);
          }
        }

        .el-icon+.el-icon {
          border-left: 1px solid var(--el-border-color-light);
        }
      }
    }
  }
}

.el-row .el-col {
  margin-top: var(--el-space);

  .el-card {
    cursor: pointer;

    &.is-active {
      background-color: var(--el-color-primary-light-9);
      border: 1px solid var(--el-color-primary);
    }

    :deep(.el-card__body) {
      padding: 0;
      overflow: hidden;
    }
  }
}

.el-pagination {
  align-items: center;
  justify-content: center;
}
</style>
